Overview
In the previous assignment, we took the RNASeq data from the publication Cannabidiol inhibits SARS-COV-2 replication and promotes the host innate immune response by Nguyen et al., cleaned the data, performed normalization, gene identifier mapping, and some additional preliminary analysis on the dataset. As suggested by the title, the authors of the publication studied the effects of cannabidiol on SARS-CoV-2 replication and host’s immune response. The authors hypothesized and concluded that cannabidiol inhibits SARS-CoV-2 replication by up-regulating the host IRE1α ribonuclease endoplasmic reticulum (ER) stress response and interferon signaling pathways. The experiment conditions from in the dataset can be categorized into
- Infection with SARS-CoV-2, no treatment
- Infection with SARS-CoV-2, treatment with Cannabidiol
- No infection, no treatment
- No infection, treatment with Cannabidiol
with 3 replicates for each test condition.
We obtained the dataset from GEO with ID GSE168797, associated with the study Cannabidiol inhibits SARS-COV-2 replication and promotes the host innate immune response published on Science Advances. Out of the total of 57832 genes, 13705 remained after removing low counts and genes with duplicate identifiers.
Data normalization is performed using TMM with the edgeR package. Normalization corrects the large deviation of the means of untreated groups from the groups treated with CBD, while still preserving some of the characteristics of the original sample distribution.

We observe separation of groups after normalization.

We will revisit this figure later when performing differential gene expression analysis.
Identifier mapping was performed using the package biomaRt with data from Ensembl. The Ensembl gene IDs in the original dataset are mapped to the corresponding HUGO gene symbols. The final dataset included 13705 genes with unique identifiers.
Setup
In this section, we import and install the necessary packages for this assignment, in which we will conduct a differential expression analysis using the normalized dataset and a thresholded over-representation analysis.
Differential Expression Analysis using edgeR
In this section, we are going to perform differential expression analysis.
Let us first examine the normalized data.
Normalized gene counts
| |
CBD_infect-1 |
CBD_infect-2 |
CBD_infect-3 |
Veh_infect-1 |
Veh_infect-2 |
Veh_infect-3 |
| TSPAN6 |
31.887883 |
34.611576 |
36.856052 |
27.579725 |
26.797481 |
25.940554 |
| DPM1 |
50.041084 |
51.301886 |
54.306630 |
45.221632 |
44.700001 |
45.116977 |
| SCYL3 |
10.913215 |
9.376985 |
9.433715 |
18.667599 |
17.497179 |
19.244748 |
| C1orf112 |
7.790084 |
9.467497 |
9.917955 |
17.755873 |
17.587255 |
19.335847 |
| CFH |
17.425654 |
19.731495 |
18.365254 |
29.699489 |
23.194459 |
29.037933 |
| FUCA2 |
47.893932 |
54.397378 |
54.772936 |
33.460361 |
31.796675 |
31.588716 |
| GCLC |
149.679627 |
160.893142 |
162.830217 |
107.652101 |
100.186550 |
108.271635 |
| NFYA |
20.903687 |
23.514873 |
24.893528 |
36.446265 |
40.443930 |
38.421171 |
| STPG1 |
16.094774 |
12.888830 |
13.253831 |
6.496051 |
6.575516 |
7.082978 |
| NIPAL3 |
23.512212 |
21.306394 |
20.822324 |
12.559032 |
11.642267 |
9.770410 |
Sample groups
| |
group |
lib.size |
norm.factors |
| CBD_infect-1 |
CBD |
673771.1 |
1 |
| CBD_infect-2 |
CBD |
677449.4 |
1 |
| CBD_infect-3 |
CBD |
685317.7 |
1 |
| Veh_infect-1 |
Veh |
782981.3 |
1 |
| Veh_infect-2 |
Veh |
781343.9 |
1 |
| Veh_infect-3 |
Veh |
793046.5 |
1 |
Workflow
We will be calculating differential expression following this general workflow:
Create deisng matrix. We will ensure that all factors that could contribute to differential expression is accounted for in the design matrix.
Use a mean-variance plot to confirm that the data follows the negative binomial distribution assumption for using the quasi-likelihood model in edgeR.
Fit our data to the model and calculated p-value and corrected p-value.
Use a threshold to extract differentially expressed genes with statistically significant differences.
Plot and visualize.
Creating the Design Matrix
In order to perform statistical testing, we need a design matrix the defines our model. Notice that in our dataset, there are three factors:
- Treatment with CBD
- Infection status (infected or not)
- Patient
Hence, ideally, we would like to account for all three factors in our design matrix.
Design matrix
| (Intercept) |
samples$patient2 |
samples$patient3 |
samples$cbd_treatmentCBD |
samples$infectedmock |
| 1 |
0 |
0 |
1 |
0 |
| 1 |
1 |
0 |
1 |
0 |
| 1 |
0 |
1 |
1 |
0 |
| 1 |
0 |
0 |
0 |
0 |
| 1 |
1 |
0 |
0 |
0 |
| 1 |
0 |
1 |
0 |
0 |
| 1 |
0 |
0 |
1 |
1 |
| 1 |
1 |
0 |
1 |
1 |
| 1 |
0 |
1 |
1 |
1 |
| 1 |
0 |
0 |
0 |
1 |
| 1 |
1 |
0 |
0 |
1 |
| 1 |
0 |
1 |
0 |
1 |
Distribution of Data
For our downstream analysis, we are going to use edgeR. We chose edgeR because it is specifically designed for RNASeq data. However, one important underlying assumption for using the quasi-likelihood model is that the data follows a negative binomial distribution. We need to verify that our dataset indeed meets that assumption.
Let us the calculate the dispersion and plot to visualize the mean-variance relationship.
edgeR::plotMeanVar(d,
show.raw.vars = TRUE,
show.tagwise.vars = TRUE,
NBline = TRUE,
show.ave.raw.vars = TRUE,
show.binned.common.disp.vars = TRUE,
main = "Mean-Variance Plot for Variance and Dispersion of Our Data")
# display legend
legend("topleft",
legend=c("Raw Data", "Tagwise Dispersion", "Average Raw Variances",
"Binned Common Dispersion", "Negative Binomial Line"),
col = c("grey", "lightblue", "maroon", "red", "dodgerblue2"), pch=c(1,1,4,4,NA), lty=c(0,0,0,0,1), lwd=c(1,1,1,1,2), cex=0.6)

As demonstrated by the mean-variance plot above, we can see that the dispersion and variance of our data indeed roughly follows the negative binomial distribution.
Analysis Using edgeR
Now, we have created the design matrix and verified the assumption for the data to be negative-binomially distributed, we can proceed to the next stage of our analysis and perform statistical testing and corrections to ensure that we only get significantly differentially expressed genes. We used the quasi-likelihood models since our dataset is from an RNASeq experiment and quasi-likelihood models are best suited to handle RNASeq data.
Once we have fit the model, we can proceed to calculate differential expression. Recall that our goal is to verify the role of cannabidiol in affecting the replication ability of SARS-CoV-2, so we will be using cbd_treatment as the contrast.
Top differentially expressed genes
| |
logFC |
logCPM |
F |
PValue |
FDR |
| DNAJB9 |
3.296477 |
6.632298 |
2376.139 |
1.174076e-13 |
1.225637e-09 |
| IGFBP1 |
4.315555 |
7.225448 |
2191.283 |
1.788598e-13 |
1.225637e-09 |
| HSPA5 |
3.721184 |
11.833327 |
1920.096 |
3.552926e-13 |
1.623095e-09 |
| CRELD2 |
3.023632 |
6.669438 |
1395.860 |
1.858463e-12 |
5.742205e-09 |
| KIF20A |
-2.327554 |
5.891384 |
1344.930 |
2.253309e-12 |
5.742205e-09 |
| ADGRF4 |
2.315894 |
4.618755 |
1287.278 |
2.827571e-12 |
5.742205e-09 |
| GABARAPL1 |
2.351451 |
6.414219 |
1278.222 |
2.932903e-12 |
5.742205e-09 |
| NDRG4 |
1.776359 |
6.129025 |
1133.516 |
5.463712e-12 |
9.159587e-09 |
| HERPUD1 |
3.400467 |
8.195296 |
1061.159 |
7.686235e-12 |
9.159587e-09 |
| STC2 |
2.742212 |
6.444858 |
1059.247 |
7.758262e-12 |
9.159587e-09 |
We can examine the number of genes pass the threshold and correction. We are using 0.05 as the threshold for p-value as it is commonly used in practice.
The threshold of 0.05 gives us quite a lot of genes, in order to get more meaningful hits in the downstream gene enrichment analysis, we will make the thershold more stringent.
Visualization of Differentially Expressed Genes
Now we can retrieve the list of differential expressed genes and visualize using different plots. We will first plot them on a volcano plot. Each gene is represented by a point in the plot. The horizontal axis of the plot is the \(\log_2\) fold change and the vertical axis is the \(-\log_{10}p\) which indicates the statistical significance of each gene (how likely the differential is due to actual biological variation).

Next, we will visualize the upregulated and downregulated genes across different test conditions using a heatmap.

Discussion
Initially, I used the p-value of 0.05 as it is widely used in practice. This gives us 5501 genes prior to correction. This is quite a large number of genes, so we changed the p-value threshold to 0.01 to limit the number of genes included. We further added the criteria that a gene must have an absolute log fold change greater than 1.5. By doing so, we are contraining ourselves to only get the genes that are highly differentially expressed with high statistical significance.
For correction, we used Benjamini-Hochberg. The two main methods discussed for correcting family-wise false discovery rate are Bonferroni and Benjamini-Hochberg correction. We want to get meaningful hits without excluding statistically significant ones. Bonferroni’s method is overly stringent so it is not quite suitable for our purposes. Using Benjamini-Hochberg will give us a richer set of genes that we can use for downstream analysis.
Volcano plot shown above. Note that we also applied the restriction that only genes with aboslute log fold change greater than 1.5 are to be included.
There is significant clustering within conditions. This suggests that the test condition (CBD v.s. no CBD) does have a significant effect on gene expressions.
Thresholded Overrepresentation Analysis using g:Profiler
For the final part of this assignment, we will perform a thresholded overrepresentation analysis using g:Profiler. In the previous section, we have compiled a list of differentially expressed genes. Here, we want to further divide them into upregulated and downregulated genes.
upregulated_gene_lst <- diff_exp_lst[diff_exp_lst$logFC > 0,]
downregulated_gene_lst <- diff_exp_lst[diff_exp_lst$logFC < 0,]
We use the R package for g:Profiler to perform the gene enrichment analysis. For correction, we used FDR as it is less stringent than Bonferroni and is introduced as the preferred correction method in class. We used GO Biological Process, GO Molecular Function, and KEGG as those are the ones used by the author of the original publication. For a more detailed overview of the workflow, please refer to the Discussion subsection located at the end of this section.
Upregulated Genes
Top genesets using list of upregulated genes
| term_name |
term_id |
source |
| response to endoplasmic reticulum stress |
GO:0034976 |
GO:BP |
| proteasomal protein catabolic process |
GO:0010498 |
GO:BP |
| ERAD pathway |
GO:0036503 |
GO:BP |
| ubiquitin-dependent ERAD pathway |
GO:0030433 |
GO:BP |
| proteasome-mediated ubiquitin-dependent protein catabolic process |
GO:0043161 |
GO:BP |
| autophagy |
GO:0006914 |
GO:BP |
| process utilizing autophagic mechanism |
GO:0061919 |
GO:BP |
| response to topologically incorrect protein |
GO:0035966 |
GO:BP |
| macroautophagy |
GO:0016236 |
GO:BP |
| endoplasmic reticulum to Golgi vesicle-mediated transport |
GO:0006888 |
GO:BP |
For context, let’s examine the top term from each data source.
Top terms from each data source using list of upregulated genes
| |
term_name |
term_id |
source |
| 1 |
response to endoplasmic reticulum stress |
GO:0034976 |
GO:BP |
| 331 |
unfolded protein binding |
GO:0051082 |
GO:MF |
| 401 |
Protein processing in endoplasmic reticulum |
KEGG:04141 |
KEGG |
We can visualize the distribution of top terms from each data source using an Manhattan plot. This is the distribution of terms prior to removing large terms with over 500 genes.
gprofiler2::gostplot(up_top_terms_all) %>% plotly::layout(title = "Manhattan plot showing distribution of terms \nfrom each data source using list of upregulated genes", font = list(size = 10))
Downregulated Genes
We do the same for the downregualted genes.
Top genesets using list of downregulated genes
| term_name |
term_id |
source |
| mitotic nuclear division |
GO:0140014 |
GO:BP |
| sister chromatid segregation |
GO:0000819 |
GO:BP |
| mitotic sister chromatid segregation |
GO:0000070 |
GO:BP |
| nuclear division |
GO:0000280 |
GO:BP |
| chromosome segregation |
GO:0007059 |
GO:BP |
| organelle fission |
GO:0048285 |
GO:BP |
| nuclear chromosome segregation |
GO:0098813 |
GO:BP |
| cell cycle phase transition |
GO:0044770 |
GO:BP |
| regulation of cell cycle phase transition |
GO:1901987 |
GO:BP |
| DNA replication |
GO:0006260 |
GO:BP |
Top terms from each data source using list of downregulated genes
| |
term_name |
term_id |
source |
| 1 |
mitotic nuclear division |
GO:0140014 |
GO:BP |
| 474 |
chromatin binding |
GO:0003682 |
GO:MF |
| 535 |
Cell cycle |
KEGG:04110 |
KEGG |
Plot the Manhattan plot showing distribution of terms from each data source using list of downregulated genes.
gprofiler2::gostplot(down_top_terms_all) %>% plotly::layout(title = "Manhattan plot showing distribution of terms\n from each data source using list of downregulated genes", font = list(size = 10))
All Differentially Expressed Genes
Finally, for all differentially expressed genes.
Top genesets using list of all differentially expressed genes
| term_name |
term_id |
source |
| mitotic sister chromatid segregation |
GO:0000070 |
GO:BP |
| mitotic nuclear division |
GO:0140014 |
GO:BP |
| sister chromatid segregation |
GO:0000819 |
GO:BP |
| response to endoplasmic reticulum stress |
GO:0034976 |
GO:BP |
| proteasomal protein catabolic process |
GO:0010498 |
GO:BP |
| organelle fission |
GO:0048285 |
GO:BP |
| chromosome segregation |
GO:0007059 |
GO:BP |
| nuclear chromosome segregation |
GO:0098813 |
GO:BP |
| nuclear division |
GO:0000280 |
GO:BP |
| regulation of cell cycle phase transition |
GO:1901987 |
GO:BP |
Top terms from each data source using list of all differentially expressed genes
| |
term_name |
term_id |
source |
| 1 |
mitotic sister chromatid segregation |
GO:0000070 |
GO:BP |
| 514 |
cadherin binding |
GO:0045296 |
GO:MF |
| 583 |
Protein processing in endoplasmic reticulum |
KEGG:04141 |
KEGG |
gprofiler2::gostplot(top_terms_all) %>% plotly::layout(title = "Manhattan plot showing distribution of terms from each data source", font = list(size = 10))
Discussion
We used g:Profiler as we have extensively discussed about it in class. It has a nice web-based interface as well as easy-to-use APIs in the form of an R package. Furthermore, the data sources on g:Profiler is frequently updated and include the data sources that we are most interested in.
We used GO Biological Process, GO Molecular Function, and KEGO. We chose these data sources since they are also used by the author of the original paper from which I obtained the dataset. However, since KEGO is a commercial data source, if it was not for that fact that the original paper used it, I would personally refrain from using it. The original author also used other data sources including Canonical Pathways but since it is not part of g:Profiler, we did not include these data sources. The annotation source versions are as follows: Ensembl 105, Ensembl Genomes 52 (database built on 2022-02-14)
For all three analysis (using upregulated, downregulated, all differentially expressed), we used a threshold between 2 and 500. We set the upper bound to 500 because we do not want to include overly broad and generic terms that will not give us meaningful insights into the roles of the differentially expressed genes. The set of upregulated genes returned 433 genesets; the set of downregulated genes returned 560 genesets; the set of all differentially expressed genes returned 616 gene sets.
The result using the whole list (set of all differentially expressed genes) is more predominantly represented by the downregulated genes. It also does not provide a lot of insights into the roles of the genes as it is a mix of drastically different and seemingly unrelated terms (e.g. mitotic nuclear division, organelle fission, response to endoplasmic reticulum stress, etc.). However, by using separating into upregualted and downregulated genes and performing the gene enrichment analysis separately, we get more meaningful terms: the upregualted genes are mostly associated with pathways and processes involving endoplasmic reticulum whereas the downregulated genes are mostly associated with the cell cycle.
Interpretation
Yes. The overrepresentation analysis results support the conclusion discussed in the original paper. The original paper claims that CBD treatment can inhibit SARS-CoV-2 replication through the host’s ER stress response pathway. Although we were not able to verify whether or not this has any affect on SARS-CoV-2 replication, we are able to confirm based on the top terms returned by the overrepresentation analysis that the genes associated with ER stress response are indeed upregulated in the samples treated with CBD.
The conclusion that CBD is correlated to reduced risk or severity of SARS-CoV-2 is supported by testing adult patients as presented by the original paper. There are also other papers who discussed the role of CBD in SARS-CoV-2 infection (van Breeman et al.). The result from our overrepresentation analysis is supported by the original paper, in which the author has also performed gene enrichment analysis with similar outcomes. However, since this is still an early research in this topic and SARS-CoV-2 continues to evolve, there does not seem to be other unrelated groups who could provide additional supporting evidence to our results from the overrepresentation analysis besides the original paper.
References
- Chen Y, Lun ATL, Smyth GK (2016). From reads to genes to pathways: differential expression analysis of RNA-Seq experiments using Rsubread and the edgeR quasi-likelihood pipeline. F1000Research 5, 1438
- Durinck, S., Spellman, P. T., Birney, E., & Huber, W. (2009). Mapping identifiers for the integration of genomic datasets with the R/Bioconductor package biomaRt. Nature - protocols, 4(8), 1184–1191. https://doi.org/10.1038/nprot.2009.97
- Martin Morgan (2021). BiocManager: Access the Bioconductor Project Package Repository. R package version 1.30.16. https://CRAN.R-project.org/package=BiocManager
- McCarthy DJ, Chen Y and Smyth GK (2012). Differential expression analysis of multifactor RNA-Seq experiments with respect to biological variation. Nucleic Acids Research 40, 4288-4297
- Nguyen, L. C., Yang, D., Nicolaescu, V., Best, T. J., Ohtsuki, T., Chen, S.-N., Friesen, J. B., Drayman, N., Mohamed, A., Dann, C., Silva, D., Gula, H., Jones, K. A., Millis, J. M., Dickinson, B. C., Tay, S., Oakes, S. A., Pauli, G. F., Meltzer, D. O., … Rosner, M. R. (2021). Cannabidiol inhibits SARS-COV-2 replication and promotes the host innate immune response. Science Advances. https://www.science.org/doi/abs/10.1126/sciadv.abi6110
- Robinson MD, McCarthy DJ and Smyth GK (2010). edgeR: a Bioconductor package for differential expression analysis of digital gene expression data. Bioinformatics 26, 139-140
- Gu, Z. (2016) Complex heatmaps reveal patterns and correlations in multidimensional genomic data. Bioinformatics.
- Kolberg L, Raudvere U, Kuzmin I, Vilo J, Peterson H (2020). “gprofiler2- an R package for gene list functional enrichment analysis and namespace conversion toolset g:Profiler.” F1000Research, 9 (ELIXIR)(709). R package version 0.2.1.
- Stefan Milton Bache and Hadley Wickham (2020). magrittr: A Forward-Pipe Operator for R. https://magrittr.tidyverse.org, https://github.com/tidyverse/magrittr.
- van Breemen, R. B., Muchiri, R. N., Bates, T. A., Weinstein, J. B., Leier, H. C., Farley, S., & Tafesse, F. G. (2022). Cannabinoids Block Cellular Entry of SARS-CoV-2 and the Emerging Variants. Journal of natural products, 85(1), 176–184. https://doi.org/10.1021/acs.jnatprod.1c00946
LS0tCnRpdGxlOiAiS2V2aW4gR2FvIC0gQXNzaWdubWVudCAyOiBEaWZmZXJlbnRpYWwgR2VuZSBleHByZXNzaW9uIGFuZCBQcmVsaW1pbmFyeSBPUkEiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAyCiAgICBtYXRoamF4OiAiaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvbWF0aGpheC8yLjcuNy9NYXRoSmF4LmpzP2NvbmZpZz1UZVgtTU1MLUFNX0NIVE1MIgotLS0KCiMgT3ZlcnZpZXcKCmBgYHtyIGExX3NvdXJjZSwgaW5jbHVkZT1GQUxTRSwgcmVzdWx0cz0naGlkZScsZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9Cm9wdGlvbnMod2Fybj0tMSkKYTFfb3V0cHV0IDwtIGtuaXRyOjprbml0X2NoaWxkKCdhc3NpZ25tZW50MS5SbWQnLCBxdWlldCA9IFRSVUUpCmBgYAoKSW4gdGhlIHByZXZpb3VzIGFzc2lnbm1lbnQsIHdlIHRvb2sgdGhlIFJOQVNlcSBkYXRhIGZyb20gdGhlIHB1YmxpY2F0aW9uICpDYW5uYWJpZGlvbCBpbmhpYml0cyBTQVJTLUNPVi0yIHJlcGxpY2F0aW9uIGFuZCBwcm9tb3RlcyB0aGUgaG9zdCBpbm5hdGUgaW1tdW5lIHJlc3BvbnNlKiBieSBOZ3V5ZW4gZXQgYWwuLCBjbGVhbmVkIHRoZSBkYXRhLCBwZXJmb3JtZWQgbm9ybWFsaXphdGlvbiwgZ2VuZSBpZGVudGlmaWVyIG1hcHBpbmcsIGFuZCBzb21lIGFkZGl0aW9uYWwgcHJlbGltaW5hcnkgYW5hbHlzaXMgb24gdGhlIGRhdGFzZXQuIEFzIHN1Z2dlc3RlZCBieSB0aGUgdGl0bGUsIHRoZSBhdXRob3JzIG9mIHRoZSBwdWJsaWNhdGlvbiBzdHVkaWVkIHRoZSBlZmZlY3RzIG9mIGNhbm5hYmlkaW9sIG9uIFNBUlMtQ29WLTIgcmVwbGljYXRpb24gYW5kIGhvc3QncyBpbW11bmUgcmVzcG9uc2UuIFRoZSBhdXRob3JzIGh5cG90aGVzaXplZCBhbmQgY29uY2x1ZGVkIHRoYXQgY2FubmFiaWRpb2wgaW5oaWJpdHMgU0FSUy1Db1YtMiByZXBsaWNhdGlvbiBieSB1cC1yZWd1bGF0aW5nIHRoZSBob3N0IElSRTHOsSByaWJvbnVjbGVhc2UgZW5kb3BsYXNtaWMgcmV0aWN1bHVtIChFUikgc3RyZXNzIHJlc3BvbnNlIGFuZCBpbnRlcmZlcm9uIHNpZ25hbGluZyBwYXRod2F5cy4gVGhlIGV4cGVyaW1lbnQgY29uZGl0aW9ucyBmcm9tIGluIHRoZSBkYXRhc2V0IGNhbiBiZSBjYXRlZ29yaXplZCBpbnRvCgotIEluZmVjdGlvbiB3aXRoIFNBUlMtQ29WLTIsIG5vIHRyZWF0bWVudAotIEluZmVjdGlvbiB3aXRoIFNBUlMtQ29WLTIsIHRyZWF0bWVudCB3aXRoIENhbm5hYmlkaW9sCi0gTm8gaW5mZWN0aW9uLCBubyB0cmVhdG1lbnQKLSBObyBpbmZlY3Rpb24sIHRyZWF0bWVudCB3aXRoIENhbm5hYmlkaW9sCgp3aXRoIDMgcmVwbGljYXRlcyBmb3IgZWFjaCB0ZXN0IGNvbmRpdGlvbi4KCldlIG9idGFpbmVkIHRoZSBkYXRhc2V0IGZyb20gR0VPIHdpdGggSUQgR1NFMTY4Nzk3LCBhc3NvY2lhdGVkIHdpdGggdGhlIHN0dWR5ICpDYW5uYWJpZGlvbCBpbmhpYml0cyBTQVJTLUNPVi0yIHJlcGxpY2F0aW9uIGFuZCBwcm9tb3RlcyB0aGUgaG9zdCBpbm5hdGUgaW1tdW5lIHJlc3BvbnNlKiBwdWJsaXNoZWQgb24gU2NpZW5jZSBBZHZhbmNlcy4gT3V0IG9mIHRoZSB0b3RhbCBvZiA1NzgzMiBnZW5lcywgMTM3MDUgcmVtYWluZWQgYWZ0ZXIgcmVtb3ZpbmcgbG93IGNvdW50cyBhbmQgZ2VuZXMgd2l0aCBkdXBsaWNhdGUgaWRlbnRpZmllcnMuCgpEYXRhIG5vcm1hbGl6YXRpb24gaXMgcGVyZm9ybWVkIHVzaW5nIFRNTSB3aXRoIHRoZSBlZGdlUiBwYWNrYWdlLiBOb3JtYWxpemF0aW9uIGNvcnJlY3RzIHRoZSBsYXJnZSBkZXZpYXRpb24gb2YgdGhlIG1lYW5zIG9mIHVudHJlYXRlZCBncm91cHMgZnJvbSB0aGUgZ3JvdXBzIHRyZWF0ZWQgd2l0aCBDQkQsIHdoaWxlIHN0aWxsIHByZXNlcnZpbmcgc29tZSBvZiB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBvcmlnaW5hbCBzYW1wbGUgZGlzdHJpYnV0aW9uLgoKYGBge3Igbm9ybWFsaXplZF9kYXRhX3Bsb3QsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpjb3VudHNfZGVuc2l0eV9ub3JtYWxpemVkIDwtIGFwcGx5KGxvZzIobm9ybWFsaXplZF9jb3VudHMpLCAyLCBkZW5zaXR5KQoKeGxpbSA8LSAwOyB5bGltIDwtIDAKZm9yIChpIGluIDE6bGVuZ3RoKGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWQpKSB7CiAgeGxpbSA8LSByYW5nZShjKHhsaW0sIGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWRbW2ldXSR4KSk7CiAgeWxpbSA8LSByYW5nZShjKHlsaW0sIGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWRbW2ldXSR5KSkKfQpjb2xzIDwtIHJhaW5ib3cobGVuZ3RoKGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWQpKQpsdHlzIDwtIHJlcCgxLCBsZW5ndGgoY291bnRzX2RlbnNpdHlfbm9ybWFsaXplZCkpCgpwbG90KGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWRbWzFdXSwgeGxpbSA9IHhsaW0sIHlsaW0gPSB5bGltLCB0eXBlID0gIm4iLCB5bGFiID0gIlNtb290aGluZyBkZW5zaXR5IG9mIGxvZzItQ1BNIiwgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgY291bnQgZGVuc2l0eSBmb3IgZWFjaCBleHBlcmltZW50IGNvbmRpdGlvbiAobm9ybWFsaXplZCkiLCBjZXgubGFiID0gMC44NSkKZm9yIChpIGluIDE6bGVuZ3RoKGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWQpKQogIGxpbmVzKGNvdW50c19kZW5zaXR5X25vcm1hbGl6ZWRbW2ldXSwgY29sID0gY29sc1tpXSwgbHR5ID0gbHR5c1tpXSkKbGVnZW5kKCJ0b3ByaWdodCIsIGNvbG5hbWVzKGRhdGEycGxvdCksIGNvbD1jb2xzLCBsdHk9bHR5cywgY2V4PTAuNzUsIGJvcmRlcj0iYmx1ZSIsIHRleHQuY29sID0gImdyZWVuNCIsIG1lcmdlID0gVFJVRSwgYmcgPSAiZ3JheTkwIikKYGBgCgpXZSBvYnNlcnZlIHNlcGFyYXRpb24gb2YgZ3JvdXBzIGFmdGVyIG5vcm1hbGl6YXRpb24uCgpgYGB7ciBhMV9tZHMsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpsaW1tYTo6cGxvdE1EUyhsb2cyKG5vcm1hbGl6ZWRfY291bnRzKSwgbGFiZWxzPXJvd25hbWVzKHNhbXBsZXMpLCBjb2wgPSBjKCJkYXJrZ3JlZW4iLCJibHVlIilbZmFjdG9yKHNhbXBsZXMkY2JkX3RyZWF0bWVudCldLCBtYWluID0gIk1EUyBwbG90IGFmdGVyIG5vcm1hbGl6YXRpb24gc2hvd2luZyBkaXN0YW5jZXMgYmV0d2VlbiBzYW1wbGVzIikKbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kPXJvd25hbWVzKHNhbXBsZXMpLCBmaWxsPWMoImRhcmtncmVlbiIsImJsdWUiKVtmYWN0b3Ioc2FtcGxlcyRjYmRfdHJlYXRtZW50KV0pCmBgYAoKV2Ugd2lsbCByZXZpc2l0IHRoaXMgZmlndXJlIGxhdGVyIHdoZW4gcGVyZm9ybWluZyBkaWZmZXJlbnRpYWwgZ2VuZSBleHByZXNzaW9uIGFuYWx5c2lzLgoKSWRlbnRpZmllciBtYXBwaW5nIHdhcyBwZXJmb3JtZWQgdXNpbmcgdGhlIHBhY2thZ2UgYmlvbWFSdCB3aXRoIGRhdGEgZnJvbSBFbnNlbWJsLiBUaGUgRW5zZW1ibCBnZW5lIElEcyBpbiB0aGUgb3JpZ2luYWwgZGF0YXNldCBhcmUgbWFwcGVkIHRvIHRoZSBjb3JyZXNwb25kaW5nIEhVR08gZ2VuZSBzeW1ib2xzLiBUaGUgZmluYWwgZGF0YXNldCBpbmNsdWRlZCAxMzcwNSBnZW5lcyB3aXRoIHVuaXF1ZSBpZGVudGlmaWVycy4KCiMgU2V0dXAKCkluIHRoaXMgc2VjdGlvbiwgd2UgaW1wb3J0IGFuZCBpbnN0YWxsIHRoZSBuZWNlc3NhcnkgcGFja2FnZXMgZm9yIHRoaXMgYXNzaWdubWVudCwgaW4gd2hpY2ggd2Ugd2lsbCBjb25kdWN0IGEgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgdXNpbmcgdGhlIG5vcm1hbGl6ZWQgZGF0YXNldCBhbmQgYSB0aHJlc2hvbGRlZCBvdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzLgoKYGBge3IgYTJfcGFja2FnZXMsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIm1hZ3JpdHRyIikpCiAgaW5zdGFsbC5wYWNrYWdlcygibWFncml0dHIiKQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImNpcmNsaXplIiwgcXVpZXRseSA9IFRSVUUpKQogICAgaW5zdGFsbC5wYWNrYWdlcygiY2lyY2xpemUiKQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkNvbXBsZXhIZWF0bWFwIiwgcXVpZXRseSA9IFRSVUUpKQogICAgQmlvY01hbmFnZXI6Omluc3RhbGwoIkNvbXBsZXhIZWF0bWFwIikKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJncHJvZmlsZXIyIiwgcXVpZXRseSA9IFRSVUUpKQogICAgQmlvY01hbmFnZXI6Omluc3RhbGwoImdwcm9maWxlcjIiKQoKIyBlZGdlUiBhbmQgb3RoZXIgcGFja2FnZXMgYXJlIGltcG9ydGVkIGluIEExLCB3aGljaCBpcyBzb3VyY2VkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIG5vdGVib29rCgpsaWJyYXJ5KG1hZ3JpdHRyKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KG1lc3NhZ2UgPSBGQUxTRSkKYGBgCgojIERpZmZlcmVudGlhbCBFeHByZXNzaW9uIEFuYWx5c2lzIHVzaW5nIGVkZ2VSCgpJbiB0aGlzIHNlY3Rpb24sIHdlIGFyZSBnb2luZyB0byBwZXJmb3JtIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzLgoKTGV0IHVzIGZpcnN0IGV4YW1pbmUgdGhlIG5vcm1hbGl6ZWQgZGF0YS4KCmBgYHtyIG5vcm1hbGl6ZWRfZGF0YSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmtuaXRyOjprYWJsZShkWzE6MTAsMTo2XSRjb3VudHMsIGNhcHRpb24gPSAiTm9ybWFsaXplZCBnZW5lIGNvdW50cyIpICU+JSBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCJzdHJpcGVkIikKa25pdHI6OmthYmxlKGRbMToxMCwxOjZdJHNhbXBsZXMsIGNhcHRpb24gPSAiU2FtcGxlIGdyb3VwcyIpICU+JSBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCJzdHJpcGVkIikKYGBgCiMjIFdvcmtmbG93CgpXZSB3aWxsIGJlIGNhbGN1bGF0aW5nIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGZvbGxvd2luZyB0aGlzIGdlbmVyYWwgd29ya2Zsb3c6CgoxLiBDcmVhdGUgZGVpc25nIG1hdHJpeC4gV2Ugd2lsbCBlbnN1cmUgdGhhdCBhbGwgZmFjdG9ycyB0aGF0IGNvdWxkIGNvbnRyaWJ1dGUgdG8gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gaXMgYWNjb3VudGVkIGZvciBpbiB0aGUgZGVzaWduIG1hdHJpeC4KCjIuIFVzZSBhIG1lYW4tdmFyaWFuY2UgcGxvdCB0byBjb25maXJtIHRoYXQgdGhlIGRhdGEgZm9sbG93cyB0aGUgbmVnYXRpdmUgYmlub21pYWwgZGlzdHJpYnV0aW9uIGFzc3VtcHRpb24gZm9yIHVzaW5nIHRoZSBxdWFzaS1saWtlbGlob29kIG1vZGVsIGluIGVkZ2VSLgoKMy4gRml0IG91ciBkYXRhIHRvIHRoZSBtb2RlbCBhbmQgY2FsY3VsYXRlZCBwLXZhbHVlIGFuZCBjb3JyZWN0ZWQgcC12YWx1ZS4KCjQuIFVzZSBhIHRocmVzaG9sZCB0byBleHRyYWN0IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyB3aXRoIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMuCgo1LiBQbG90IGFuZCB2aXN1YWxpemUuCgojIyBDcmVhdGluZyB0aGUgRGVzaWduIE1hdHJpeAoKSW4gb3JkZXIgdG8gcGVyZm9ybSBzdGF0aXN0aWNhbCB0ZXN0aW5nLCB3ZSBuZWVkIGEgZGVzaWduIG1hdHJpeCB0aGUgZGVmaW5lcyBvdXIgbW9kZWwuIE5vdGljZSB0aGF0IGluIG91ciBkYXRhc2V0LCB0aGVyZSBhcmUgdGhyZWUgZmFjdG9yczogCgoxLiBUcmVhdG1lbnQgd2l0aCBDQkQKMi4gSW5mZWN0aW9uIHN0YXR1cyAoaW5mZWN0ZWQgb3Igbm90KQozLiBQYXRpZW50CgpIZW5jZSwgaWRlYWxseSwgd2Ugd291bGQgbGlrZSB0byBhY2NvdW50IGZvciBhbGwgdGhyZWUgZmFjdG9ycyBpbiBvdXIgZGVzaWduIG1hdHJpeC4KCmBgYHtyIGRlc2lnbl9tYXRyaXgsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQptb2RlbF9kZXNpZ24gPC0gbW9kZWwubWF0cml4KH4gc2FtcGxlcyRwYXRpZW50ICsgc2FtcGxlcyRjYmRfdHJlYXRtZW50ICsgc2FtcGxlcyRpbmZlY3RlZCkKbW9kZWxfZGVzaWduWyw0XSA8LSAhbW9kZWxfZGVzaWduWyw0XQpjb2xuYW1lcyhtb2RlbF9kZXNpZ24pWzRdIDwtICJzYW1wbGVzJGNiZF90cmVhdG1lbnRDQkQiCmtuaXRyOjprYWJsZShtb2RlbF9kZXNpZ24sIGNhcHRpb24gPSAiRGVzaWduIG1hdHJpeCIpICU+JQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoInN0cmlwZWQiKQpgYGAKCiMjIERpc3RyaWJ1dGlvbiBvZiBEYXRhCgpGb3Igb3VyIGRvd25zdHJlYW0gYW5hbHlzaXMsIHdlIGFyZSBnb2luZyB0byB1c2UgZWRnZVIuIFdlIGNob3NlIGVkZ2VSIGJlY2F1c2UgaXQgaXMgc3BlY2lmaWNhbGx5IGRlc2lnbmVkIGZvciBSTkFTZXEgZGF0YS4gSG93ZXZlciwgb25lIGltcG9ydGFudCB1bmRlcmx5aW5nIGFzc3VtcHRpb24gZm9yIHVzaW5nIHRoZSBxdWFzaS1saWtlbGlob29kIG1vZGVsIGlzIHRoYXQgdGhlIGRhdGEgZm9sbG93cyBhIG5lZ2F0aXZlIGJpbm9taWFsIGRpc3RyaWJ1dGlvbi4gV2UgbmVlZCB0byB2ZXJpZnkgdGhhdCBvdXIgZGF0YXNldCBpbmRlZWQgbWVldHMgdGhhdCBhc3N1bXB0aW9uLgoKTGV0IHVzIHRoZSBjYWxjdWxhdGUgdGhlIGRpc3BlcnNpb24gYW5kIHBsb3QgdG8gdmlzdWFsaXplIHRoZSBtZWFuLXZhcmlhbmNlIHJlbGF0aW9uc2hpcC4KCmBgYHtyIGRpc3BlcnNpb25fY2FsYywgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmQgPC0gZWRnZVI6OkRHRUxpc3QoY291bnRzID0gbm9ybWFsaXplZF9jb3VudHNfYW5ub3RbLDM6bmNvbChub3JtYWxpemVkX2NvdW50c19hbm5vdCldLCBncm91cCA9IHNhbXBsZXMkY2JkX3RyZWF0bWVudCkKZCA8LSBlZGdlUjo6ZXN0aW1hdGVEaXNwKGQsIG1vZGVsX2Rlc2lnbikKYGBgCgpgYGB7ciBtZWFuX3Zhcl9wbG90fQplZGdlUjo6cGxvdE1lYW5WYXIoZCwKICAgICAgICAgICAgICAgICAgIHNob3cucmF3LnZhcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgc2hvdy50YWd3aXNlLnZhcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgTkJsaW5lID0gVFJVRSwKICAgICAgICAgICAgICAgICAgIHNob3cuYXZlLnJhdy52YXJzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgIHNob3cuYmlubmVkLmNvbW1vbi5kaXNwLnZhcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgbWFpbiA9ICJNZWFuLVZhcmlhbmNlIFBsb3QgZm9yIFZhcmlhbmNlIGFuZCBEaXNwZXJzaW9uIG9mIE91ciBEYXRhIikKIyBkaXNwbGF5IGxlZ2VuZApsZWdlbmQoInRvcGxlZnQiLCAKICAgICAgIGxlZ2VuZD1jKCJSYXcgRGF0YSIsICJUYWd3aXNlIERpc3BlcnNpb24iLCAiQXZlcmFnZSBSYXcgVmFyaWFuY2VzIiwgCiAgICAgICAgICAgICAgICAiQmlubmVkIENvbW1vbiBEaXNwZXJzaW9uIiwgIk5lZ2F0aXZlIEJpbm9taWFsIExpbmUiKSwgCiAgICAgICBjb2wgPSBjKCJncmV5IiwgImxpZ2h0Ymx1ZSIsICJtYXJvb24iLCAicmVkIiwgImRvZGdlcmJsdWUyIiksIHBjaD1jKDEsMSw0LDQsTkEpLCBsdHk9YygwLDAsMCwwLDEpLCBsd2Q9YygxLDEsMSwxLDIpLCBjZXg9MC42KQpgYGAKCkFzIGRlbW9uc3RyYXRlZCBieSB0aGUgbWVhbi12YXJpYW5jZSBwbG90IGFib3ZlLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGRpc3BlcnNpb24gYW5kIHZhcmlhbmNlIG9mIG91ciBkYXRhIGluZGVlZCByb3VnaGx5IGZvbGxvd3MgdGhlIG5lZ2F0aXZlIGJpbm9taWFsIGRpc3RyaWJ1dGlvbi4KCiMjIEFuYWx5c2lzIFVzaW5nIGVkZ2VSCgpOb3csIHdlIGhhdmUgY3JlYXRlZCB0aGUgZGVzaWduIG1hdHJpeCBhbmQgdmVyaWZpZWQgdGhlIGFzc3VtcHRpb24gZm9yIHRoZSBkYXRhIHRvIGJlIG5lZ2F0aXZlLWJpbm9taWFsbHkgZGlzdHJpYnV0ZWQsIHdlIGNhbiBwcm9jZWVkIHRvIHRoZSBuZXh0IHN0YWdlIG9mIG91ciBhbmFseXNpcyBhbmQgcGVyZm9ybSBzdGF0aXN0aWNhbCB0ZXN0aW5nIGFuZCBjb3JyZWN0aW9ucyB0byBlbnN1cmUgdGhhdCB3ZSBvbmx5IGdldCBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcy4gV2UgdXNlZCB0aGUgcXVhc2ktbGlrZWxpaG9vZCBtb2RlbHMgc2luY2Ugb3VyIGRhdGFzZXQgaXMgZnJvbSBhbiBSTkFTZXEgZXhwZXJpbWVudCBhbmQgcXVhc2ktbGlrZWxpaG9vZCBtb2RlbHMgYXJlIGJlc3Qgc3VpdGVkIHRvIGhhbmRsZSBSTkFTZXEgZGF0YS4KCmBgYHtyIGZpdF9xbCwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmZpdCA8LSBlZGdlUjo6Z2xtUUxGaXQoZCwgbW9kZWxfZGVzaWduKQpgYGAKCk9uY2Ugd2UgaGF2ZSBmaXQgdGhlIG1vZGVsLCB3ZSBjYW4gcHJvY2VlZCB0byBjYWxjdWxhdGUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24uIFJlY2FsbCB0aGF0IG91ciBnb2FsIGlzIHRvIHZlcmlmeSB0aGUgcm9sZSBvZiBjYW5uYWJpZGlvbCBpbiBhZmZlY3RpbmcgdGhlIHJlcGxpY2F0aW9uIGFiaWxpdHkgb2YgU0FSUy1Db1YtMiwgc28gd2Ugd2lsbCBiZSB1c2luZyBgY2JkX3RyZWF0bWVudGAgYXMgdGhlIGNvbnRyYXN0LgoKYGBge3IgdGVzdF9xbCwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CnFsZiA8LSBlZGdlUjo6Z2xtUUxGVGVzdChmaXQsIGNvZWYgPSAnc2FtcGxlcyRjYmRfdHJlYXRtZW50Q0JEJykKcWxmX2RpZmZfZXhwIDwtIGVkZ2VSOjp0b3BUYWdzKHFsZiwgc29ydC5ieSA9ICJQVmFsdWUiLCBuID0gbnJvdyhub3JtYWxpemVkX2NvdW50c19hbm5vdCkpCmtuaXRyOjprYWJsZShxbGZfZGlmZl9leHBbMToxMCxdJHRhYmxlLCB0eXBlPSJodG1sIiwgZGlnaXRzID0gMjAsIGNhcHRpb24gPSAiVG9wIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyIpICU+JQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoInN0cmlwZWQiKQpgYGAKCldlIGNhbiBleGFtaW5lIHRoZSBudW1iZXIgb2YgZ2VuZXMgcGFzcyB0aGUgdGhyZXNob2xkIGFuZCBjb3JyZWN0aW9uLiBXZSBhcmUgdXNpbmcgMC4wNSBhcyB0aGUgdGhyZXNob2xkIGZvciBwLXZhbHVlIGFzIGl0IGlzIGNvbW1vbmx5IHVzZWQgaW4gcHJhY3RpY2UuCgpgYGB7ciBjb3VudF9kaWZmX3B2YWwsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQojIG51bWJlciBvZiBnZW5lcyB0aGF0IHBhc3NlZCB0aGUgdGhyZXNob2xkCnN1bShxbGZfZGlmZl9leHAkdGFibGUkUFZhbHVlIDwgMC4wNSkKYGBgCmBgYHtyIGNvdW50X2RpZmZfZmRyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KIyBudW1iZXIgb2YgZ2VuZXMgdGhhdCBwYXNzZWQgY29ycmVjdGlvbgpzdW0ocWxmX2RpZmZfZXhwJHRhYmxlJEZEUiA8IDAuMDUpCmBgYAoKVGhlIHRocmVzaG9sZCBvZiAwLjA1IGdpdmVzIHVzIHF1aXRlIGEgbG90IG9mIGdlbmVzLCBpbiBvcmRlciB0byBnZXQgbW9yZSBtZWFuaW5nZnVsIGhpdHMgaW4gdGhlIGRvd25zdHJlYW0gZ2VuZSBlbnJpY2htZW50IGFuYWx5c2lzLCB3ZSB3aWxsIG1ha2UgdGhlIHRoZXJzaG9sZCBtb3JlIHN0cmluZ2VudC4KCmBgYHtyIGNvdW50X2RpZmZfcHZhbF9zdHJpbmdlbnQsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQojIG51bWJlciBvZiBnZW5lcyB0aGF0IHBhc3NlZCB0aGUgdGhyZXNob2xkCnN1bShxbGZfZGlmZl9leHAkdGFibGUkUFZhbHVlIDwgMC4wMSAmIGFicyhxbGZfZGlmZl9leHAkdGFibGUkbG9nRkMpID4gMS41KQpgYGAKYGBge3IgY291bnRfZmRyX3N0cmluZ2VudCwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CiMgbnVtYmVyIG9mIGdlbmVzIHRoYXQgcGFzc2VkIGNvcnJlY3Rpb24Kc3VtKHFsZl9kaWZmX2V4cCR0YWJsZSRGRFIgPCAwLjAxICYgYWJzKHFsZl9kaWZmX2V4cCR0YWJsZSRsb2dGQykgPiAxLjUpCmBgYAoKIyMgVmlzdWFsaXphdGlvbiBvZiBEaWZmZXJlbnRpYWxseSBFeHByZXNzZWQgR2VuZXMKCk5vdyB3ZSBjYW4gcmV0cmlldmUgdGhlIGxpc3Qgb2YgZGlmZmVyZW50aWFsIGV4cHJlc3NlZCBnZW5lcyBhbmQgdmlzdWFsaXplIHVzaW5nIGRpZmZlcmVudCBwbG90cy4gV2Ugd2lsbCBmaXJzdCBwbG90IHRoZW0gb24gYSB2b2xjYW5vIHBsb3QuIEVhY2ggZ2VuZSBpcyByZXByZXNlbnRlZCBieSBhIHBvaW50IGluIHRoZSBwbG90LiBUaGUgaG9yaXpvbnRhbCBheGlzIG9mIHRoZSBwbG90IGlzIHRoZSAkXGxvZ18yJCBmb2xkIGNoYW5nZSBhbmQgdGhlIHZlcnRpY2FsIGF4aXMgaXMgdGhlICQtXGxvZ197MTB9cCQgd2hpY2ggaW5kaWNhdGVzIHRoZSBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2Ugb2YgZWFjaCBnZW5lIChob3cgbGlrZWx5IHRoZSBkaWZmZXJlbnRpYWwgaXMgZHVlIHRvIGFjdHVhbCBiaW9sb2dpY2FsIHZhcmlhdGlvbikuCgpgYGB7ciB2b2xjYW5vX3Bsb3QsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQp2b2xjYW5vX2NvbG9yX3BhbGV0dGUgPSByZXAoJ2dyYXknLCB0aW1lcyA9IG5yb3cocWxmX2RpZmZfZXhwJHRhYmxlKSkKdm9sY2Fub19jb2xvcl9wYWxldHRlW3FsZl9kaWZmX2V4cCR0YWJsZSRsb2dGQyA8IDAgJiBxbGZfZGlmZl9leHAkdGFibGUkRkRSIDwgMC4wMSAmIGFicyhxbGZfZGlmZl9leHAkdGFibGUkbG9nRkMpID4gMS41XSA8LSAnYmx1ZScKdm9sY2Fub19jb2xvcl9wYWxldHRlW3FsZl9kaWZmX2V4cCR0YWJsZSRsb2dGQyA+IDAgJiBxbGZfZGlmZl9leHAkdGFibGUkRkRSIDwgMC4wMSAmIGFicyhxbGZfZGlmZl9leHAkdGFibGUkbG9nRkMpID4gMS41XSA8LSAncmVkJwoKcGxvdChxbGZfZGlmZl9leHAkdGFibGUkbG9nRkMsIAogICAgIC1sb2cocWxmX2RpZmZfZXhwJHRhYmxlJFBWYWx1ZSwgYmFzZT0xMCksIAogICAgIGNvbCA9IHZvbGNhbm9fY29sb3JfcGFsZXR0ZSwKICAgICB4bGFiID0gImxvZzIgZm9sZCBjaGFuZ2UiLAogICAgIHlsYWIgPSAiLWxvZzEwIHAiLAogICAgIG1haW4gPSAiVm9sY2FubyBwbG90IHNob3dpbmcgdXByZWd1bGF0ZWQgYW5kIGRvd25yZWd1bGF0ZWQgZ2VuZXMiCiAgICApCgpsZWdlbmQoInRvcHJpZ2h0IiwgbGVnZW5kPWMoIkRvd25yZWd1bGF0ZWQgaW4gQ0JEIHRyZWF0ZWQgY2VsbHMiLCJVcHJlZ3VsYXRlZCBpbiBDQkQgdHJlYXRlZCBjZWxscyIsICJOb3Qgc2lnbmlmaWNhbnQiKSxmaWxsID0gYygiYmx1ZSIsICJyZWQiLCAiZ3JleSIpLCBjZXggPSAwLjUpCmBgYAoKTmV4dCwgd2Ugd2lsbCB2aXN1YWxpemUgdGhlIHVwcmVndWxhdGVkIGFuZCBkb3ducmVndWxhdGVkIGdlbmVzIGFjcm9zcyBkaWZmZXJlbnQgdGVzdCBjb25kaXRpb25zIHVzaW5nIGEgaGVhdG1hcC4KCmBgYHtyIGhlYXRtYXAsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpkaWZmX2V4cF9sc3QgPC0gcWxmX2RpZmZfZXhwJHRhYmxlW3FsZl9kaWZmX2V4cCR0YWJsZSRGRFIgPCAwLjAxICYgYWJzKHFsZl9kaWZmX2V4cCR0YWJsZSRsb2dGQyksXQpkaWZmX2V4cF9sc3QkaGduY19zeW1ib2wgPC0gcm93bmFtZXMoZGlmZl9leHBfbHN0KQoKIyBub3JtYWxpemVkIGNvdW50cyBvZiBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMKbWF0X2NvdW50X25vcm1hbGl6ZWRfZGlmZiA8LSBub3JtYWxpemVkX2NvdW50c19hbm5vdFtkaWZmX2V4cF9sc3QkaGduY19zeW1ib2wsIDM6bmNvbChub3JtYWxpemVkX2NvdW50c19hbm5vdCldCiMgcmVzY2FsZSB0aGUgY291bnRzCm1hdF9jb3VudF9ub3JtYWxpemVkX2RpZmYgPC0gdChzY2FsZSh0KG1hdF9jb3VudF9ub3JtYWxpemVkX2RpZmYpKSkKaGVhdG1hcF9jb2xvcl9wYWxldHRlIDwtIGNpcmNsaXplOjpjb2xvclJhbXAyKGMobWluKG1hdF9jb3VudF9ub3JtYWxpemVkX2RpZmYpLCAwLCBtYXgobWF0X2NvdW50X25vcm1hbGl6ZWRfZGlmZikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiYmx1ZSIsICJ3aGl0ZSIsICJyZWQiKSkKQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAoYXMubWF0cml4KG1hdF9jb3VudF9ub3JtYWxpemVkX2RpZmYpLAogICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gInNjYWxlZCBub3JtYWxpemVkIGNvdW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2x1bW5zID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93X2RlbmQgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sdW1uX2RlbmQgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbCA9IGhlYXRtYXBfY29sb3JfcGFsZXR0ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sdW1uX25hbWVzID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93X25hbWVzID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uX3RpdGxlID0gIlNhbXBsZXMiLAogICAgICAgICAgICAgICAgICAgICAgICByb3dfdGl0bGUgPSAiR2VuZXMiLAogICAgICAgICAgICAgICAgICAgICAgICB1c2VfcmFzdGVyID0gVFJVRSkKYGBgCgojIyBEaXNjdXNzaW9uCgoxLiBJbml0aWFsbHksIEkgdXNlZCB0aGUgcC12YWx1ZSBvZiAwLjA1IGFzIGl0IGlzIHdpZGVseSB1c2VkIGluIHByYWN0aWNlLiBUaGlzIGdpdmVzIHVzIDU1MDEgZ2VuZXMgcHJpb3IgdG8gY29ycmVjdGlvbi4gVGhpcyBpcyBxdWl0ZSBhIGxhcmdlIG51bWJlciBvZiBnZW5lcywgc28gd2UgY2hhbmdlZCB0aGUgcC12YWx1ZSB0aHJlc2hvbGQgdG8gMC4wMSB0byBsaW1pdCB0aGUgbnVtYmVyIG9mIGdlbmVzIGluY2x1ZGVkLiBXZSBmdXJ0aGVyIGFkZGVkIHRoZSBjcml0ZXJpYSB0aGF0IGEgZ2VuZSBtdXN0IGhhdmUgYW4gYWJzb2x1dGUgbG9nIGZvbGQgY2hhbmdlIGdyZWF0ZXIgdGhhbiAxLjUuIEJ5IGRvaW5nIHNvLCB3ZSBhcmUgY29udHJhaW5pbmcgb3Vyc2VsdmVzIHRvIG9ubHkgZ2V0IHRoZSBnZW5lcyB0aGF0IGFyZSBoaWdobHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIHdpdGggaGlnaCBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UuCgoyLiBGb3IgY29ycmVjdGlvbiwgd2UgdXNlZCBCZW5qYW1pbmktSG9jaGJlcmcuIFRoZSB0d28gbWFpbiBtZXRob2RzIGRpc2N1c3NlZCBmb3IgY29ycmVjdGluZyBmYW1pbHktd2lzZSBmYWxzZSBkaXNjb3ZlcnkgcmF0ZSBhcmUgQm9uZmVycm9uaSBhbmQgQmVuamFtaW5pLUhvY2hiZXJnIGNvcnJlY3Rpb24uIFdlIHdhbnQgdG8gZ2V0IG1lYW5pbmdmdWwgaGl0cyB3aXRob3V0IGV4Y2x1ZGluZyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IG9uZXMuIEJvbmZlcnJvbmkncyBtZXRob2QgaXMgb3Zlcmx5IHN0cmluZ2VudCBzbyBpdCBpcyBub3QgcXVpdGUgc3VpdGFibGUgZm9yIG91ciBwdXJwb3Nlcy4gVXNpbmcgQmVuamFtaW5pLUhvY2hiZXJnIHdpbGwgZ2l2ZSB1cyBhIHJpY2hlciBzZXQgb2YgZ2VuZXMgdGhhdCB3ZSBjYW4gdXNlIGZvciBkb3duc3RyZWFtIGFuYWx5c2lzLgoKMy4gVm9sY2FubyBwbG90IHNob3duIGFib3ZlLiBOb3RlIHRoYXQgd2UgYWxzbyBhcHBsaWVkIHRoZSByZXN0cmljdGlvbiB0aGF0IG9ubHkgZ2VuZXMgd2l0aCBhYm9zbHV0ZSBsb2cgZm9sZCBjaGFuZ2UgZ3JlYXRlciB0aGFuIDEuNSBhcmUgdG8gYmUgaW5jbHVkZWQuCgo0LiBUaGVyZSBpcyBzaWduaWZpY2FudCBjbHVzdGVyaW5nIHdpdGhpbiBjb25kaXRpb25zLiBUaGlzIHN1Z2dlc3RzIHRoYXQgdGhlIHRlc3QgY29uZGl0aW9uIChDQkQgdi5zLiBubyBDQkQpIGRvZXMgaGF2ZSBhIHNpZ25pZmljYW50IGVmZmVjdCBvbiBnZW5lIGV4cHJlc3Npb25zLgoKIyBUaHJlc2hvbGRlZCBPdmVycmVwcmVzZW50YXRpb24gQW5hbHlzaXMgdXNpbmcgZzpQcm9maWxlcgoKRm9yIHRoZSBmaW5hbCBwYXJ0IG9mIHRoaXMgYXNzaWdubWVudCwgd2Ugd2lsbCBwZXJmb3JtIGEgdGhyZXNob2xkZWQgb3ZlcnJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIHVzaW5nIGc6UHJvZmlsZXIuIEluIHRoZSBwcmV2aW91cyBzZWN0aW9uLCB3ZSBoYXZlIGNvbXBpbGVkIGEgbGlzdCBvZiBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMuIEhlcmUsIHdlIHdhbnQgdG8gZnVydGhlciBkaXZpZGUgdGhlbSBpbnRvIHVwcmVndWxhdGVkIGFuZCBkb3ducmVndWxhdGVkIGdlbmVzLgoKYGBge3Igc3BsaXRfdXBkb3ducmVndWxhdGVkfQp1cHJlZ3VsYXRlZF9nZW5lX2xzdCA8LSBkaWZmX2V4cF9sc3RbZGlmZl9leHBfbHN0JGxvZ0ZDID4gMCxdCmRvd25yZWd1bGF0ZWRfZ2VuZV9sc3QgPC0gZGlmZl9leHBfbHN0W2RpZmZfZXhwX2xzdCRsb2dGQyA8IDAsXQpgYGAKCldlIHVzZSB0aGUgUiBwYWNrYWdlIGZvciBnOlByb2ZpbGVyIHRvIHBlcmZvcm0gdGhlIGdlbmUgZW5yaWNobWVudCBhbmFseXNpcy4gRm9yIGNvcnJlY3Rpb24sIHdlIHVzZWQgRkRSIGFzIGl0IGlzIGxlc3Mgc3RyaW5nZW50IHRoYW4gQm9uZmVycm9uaSBhbmQgaXMgaW50cm9kdWNlZCBhcyB0aGUgcHJlZmVycmVkIGNvcnJlY3Rpb24gbWV0aG9kIGluIGNsYXNzLiBXZSB1c2VkIEdPIEJpb2xvZ2ljYWwgUHJvY2VzcywgR08gTW9sZWN1bGFyIEZ1bmN0aW9uLCBhbmQgS0VHRyBhcyB0aG9zZSBhcmUgdGhlIG9uZXMgdXNlZCBieSB0aGUgYXV0aG9yIG9mIHRoZSBvcmlnaW5hbCBwdWJsaWNhdGlvbi4gRm9yIGEgbW9yZSBkZXRhaWxlZCBvdmVydmlldyBvZiB0aGUgd29ya2Zsb3csIHBsZWFzZSByZWZlciB0byB0aGUgRGlzY3Vzc2lvbiBzdWJzZWN0aW9uIGxvY2F0ZWQgYXQgdGhlIGVuZCBvZiB0aGlzIHNlY3Rpb24uCgojIyBVcHJlZ3VsYXRlZCBHZW5lcwoKYGBge3IgZ3Byb2ZpbGVyX3VwLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KdXBfdG9wX3Rlcm1zX2FsbCA8LSBncHJvZmlsZXIyOjpnb3N0KHF1ZXJ5ID0gcm93bmFtZXModXByZWd1bGF0ZWRfZ2VuZV9sc3QpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImhzYXBpZW5zIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlX2llYSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWN0aW9uX21ldGhvZCA9ICJmZHIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlcyA9IGMoIkdPOkJQIiwgIkdPOk1GIiwgIktFR0ciKSkKCnVwX3RvcF90ZXJtcyA8LSBkYXRhLmZyYW1lKAogIHRlcm1fbmFtZSA9IHVwX3RvcF90ZXJtc19hbGwkcmVzdWx0JHRlcm1fbmFtZVt1cF90b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPCA1MDAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwX3RvcF90ZXJtc19hbGwkcmVzdWx0JHRlcm1fc2l6ZSA+IDJdLAogIHRlcm1faWQgPSB1cF90b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX2lkW3VwX3RvcF90ZXJtc19hbGwkcmVzdWx0JHRlcm1fc2l6ZSA8IDUwMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cF90b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPiAyXSwKICBzb3VyY2UgPSB1cF90b3BfdGVybXNfYWxsJHJlc3VsdCRzb3VyY2VbdXBfdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplIDwgNTAwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cF90b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPiAyXQopCgprbml0cjo6a2FibGUodXBfdG9wX3Rlcm1zWzE6MTAsXSwgY2FwdGlvbiA9ICJUb3AgZ2VuZXNldHMgdXNpbmcgbGlzdCBvZiB1cHJlZ3VsYXRlZCBnZW5lcyIpICU+JSBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCJzdHJpcGVkIikKYGBgCkZvciBjb250ZXh0LCBsZXQncyBleGFtaW5lIHRoZSB0b3AgdGVybSBmcm9tIGVhY2ggZGF0YSBzb3VyY2UuCgpgYGB7ciB1cF90b3BfdGVybV9wZXJfY2F0ZWdvcnksIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQprbml0cjo6a2FibGUocmJpbmQodXBfdG9wX3Rlcm1zW3VwX3RvcF90ZXJtcyRzb3VyY2UgPT0gIkdPOkJQIixdWzEsXSwKICAgICAgICAgICAgICAgICAgIHVwX3RvcF90ZXJtc1t1cF90b3BfdGVybXMkc291cmNlID09ICJHTzpNRiIsXVsxLF0sCiAgICAgICAgICAgICAgICAgICB1cF90b3BfdGVybXNbdXBfdG9wX3Rlcm1zJHNvdXJjZSA9PSAiS0VHRyIsXVsxLF0pLAogICAgICAgICAgICAgY2FwdGlvbiA9ICJUb3AgdGVybXMgZnJvbSBlYWNoIGRhdGEgc291cmNlIHVzaW5nIGxpc3Qgb2YgdXByZWd1bGF0ZWQgZ2VuZXMiKSAlPiUKICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCJzdHJpcGVkIikKYGBgCldlIGNhbiB2aXN1YWxpemUgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0b3AgdGVybXMgZnJvbSBlYWNoIGRhdGEgc291cmNlIHVzaW5nIGFuIE1hbmhhdHRhbiBwbG90LiBUaGlzIGlzIHRoZSBkaXN0cmlidXRpb24gb2YgdGVybXMgcHJpb3IgdG8gcmVtb3ZpbmcgbGFyZ2UgdGVybXMgd2l0aCBvdmVyIDUwMCBnZW5lcy4KCmBgYHtyIHVwX2Rpc3RfcGxvdH0KZ3Byb2ZpbGVyMjo6Z29zdHBsb3QodXBfdG9wX3Rlcm1zX2FsbCkgJT4lIHBsb3RseTo6bGF5b3V0KHRpdGxlID0gIk1hbmhhdHRhbiBwbG90IHNob3dpbmcgZGlzdHJpYnV0aW9uIG9mIHRlcm1zIFxuZnJvbSBlYWNoIGRhdGEgc291cmNlIHVzaW5nIGxpc3Qgb2YgdXByZWd1bGF0ZWQgZ2VuZXMiLCBmb250ID0gbGlzdChzaXplID0gMTApKQpgYGAKCmBgYHtyIGNvdW50X3VwX3RvcF90ZXJtcywgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9Cmxlbmd0aCh1cF90b3BfdGVybXMkdGVybV9uYW1lKQpgYGAKCiMjIERvd25yZWd1bGF0ZWQgR2VuZXMKCldlIGRvIHRoZSBzYW1lIGZvciB0aGUgZG93bnJlZ3VhbHRlZCBnZW5lcy4KCmBgYHtyIGdwcm9maWxlcl9kb3duLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KZG93bl90b3BfdGVybXNfYWxsIDwtIGdwcm9maWxlcjI6Omdvc3QocXVlcnkgPSByb3duYW1lcyhkb3ducmVndWxhdGVkX2dlbmVfbHN0KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJoc2FwaWVucyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZV9pZWEgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVjdGlvbl9tZXRob2QgPSAiZmRyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZXMgPSBjKCJHTzpCUCIsICJHTzpNRiIsICJLRUdHIikpCgpkb3duX3RvcF90ZXJtcyA8LSBkYXRhLmZyYW1lKAogIHRlcm1fbmFtZSA9IGRvd25fdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9uYW1lW2Rvd25fdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplIDwgNTAwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvd25fdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplID4gMl0sCiAgdGVybV9pZCA9IGRvd25fdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9pZFtkb3duX3RvcF90ZXJtc19hbGwkcmVzdWx0JHRlcm1fc2l6ZSA8IDUwMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvd25fdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplID4gMl0sCiAgc291cmNlID0gZG93bl90b3BfdGVybXNfYWxsJHJlc3VsdCRzb3VyY2VbZG93bl90b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPCA1MDAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG93bl90b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPiAyXQopCgprbml0cjo6a2FibGUoZG93bl90b3BfdGVybXNbMToxMCxdLCBjYXB0aW9uID0gIlRvcCBnZW5lc2V0cyB1c2luZyBsaXN0IG9mIGRvd25yZWd1bGF0ZWQgZ2VuZXMiKSAlPiUga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZygic3RyaXBlZCIpCmBgYAoKYGBge3IgZG93bl90b3BfdGVybV9wZXJfY2F0ZWdvcnksIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQprbml0cjo6a2FibGUocmJpbmQoZG93bl90b3BfdGVybXNbZG93bl90b3BfdGVybXMkc291cmNlID09ICJHTzpCUCIsXVsxLF0sCiAgICAgICAgICAgICAgICAgICBkb3duX3RvcF90ZXJtc1tkb3duX3RvcF90ZXJtcyRzb3VyY2UgPT0gIkdPOk1GIixdWzEsXSwKICAgICAgICAgICAgICAgICAgIGRvd25fdG9wX3Rlcm1zW2Rvd25fdG9wX3Rlcm1zJHNvdXJjZSA9PSAiS0VHRyIsXVsxLF0pLAogICAgICAgICAgICAgY2FwdGlvbiA9ICJUb3AgdGVybXMgZnJvbSBlYWNoIGRhdGEgc291cmNlIHVzaW5nIGxpc3Qgb2YgZG93bnJlZ3VsYXRlZCBnZW5lcyIpICU+JQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoInN0cmlwZWQiKQpgYGAKUGxvdCB0aGUgTWFuaGF0dGFuIHBsb3Qgc2hvd2luZyBkaXN0cmlidXRpb24gb2YgdGVybXMgZnJvbSBlYWNoIGRhdGEgc291cmNlIHVzaW5nIGxpc3Qgb2YgZG93bnJlZ3VsYXRlZCBnZW5lcy4KCmBgYHtyIGRvd25fZGlzdF9wbG90fQpncHJvZmlsZXIyOjpnb3N0cGxvdChkb3duX3RvcF90ZXJtc19hbGwpICU+JSBwbG90bHk6OmxheW91dCh0aXRsZSA9ICJNYW5oYXR0YW4gcGxvdCBzaG93aW5nIGRpc3RyaWJ1dGlvbiBvZiB0ZXJtc1xuIGZyb20gZWFjaCBkYXRhIHNvdXJjZSB1c2luZyBsaXN0IG9mIGRvd25yZWd1bGF0ZWQgZ2VuZXMiLCBmb250ID0gbGlzdChzaXplID0gMTApKQpgYGAKCmBgYHtyIGNvdW50X2Rvd25fdG9wX3Rlcm1zLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KbGVuZ3RoKGRvd25fdG9wX3Rlcm1zJHRlcm1fbmFtZSkKYGBgCgojIyBBbGwgRGlmZmVyZW50aWFsbHkgRXhwcmVzc2VkIEdlbmVzCgpGaW5hbGx5LCBmb3IgYWxsIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcy4KCmBgYHtyIGdwcm9maWxlcl9vdmVyYWxsLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KdG9wX3Rlcm1zX2FsbCA8LSBncHJvZmlsZXIyOjpnb3N0KHF1ZXJ5ID0gcm93bmFtZXMoZGlmZl9leHBfbHN0KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJoc2FwaWVucyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZV9pZWEgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVjdGlvbl9tZXRob2QgPSAiZmRyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZXMgPSBjKCJHTzpCUCIsICJHTzpNRiIsICJLRUdHIikpCgp0b3BfdGVybXMgPC0gZGF0YS5mcmFtZSgKICB0ZXJtX25hbWUgPSB0b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX25hbWVbdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplIDwgNTAwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPiAyXSwKICB0ZXJtX2lkID0gdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9pZFt0b3BfdGVybXNfYWxsJHJlc3VsdCR0ZXJtX3NpemUgPCA1MDAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplID4gMl0sCiAgc291cmNlID0gdG9wX3Rlcm1zX2FsbCRyZXN1bHQkc291cmNlW3RvcF90ZXJtc19hbGwkcmVzdWx0JHRlcm1fc2l6ZSA8IDUwMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9wX3Rlcm1zX2FsbCRyZXN1bHQkdGVybV9zaXplID4gMl0KKQoKa25pdHI6OmthYmxlKHRvcF90ZXJtc1sxOjEwLF0sIGNhcHRpb24gPSAiVG9wIGdlbmVzZXRzIHVzaW5nIGxpc3Qgb2YgYWxsIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyIpICU+JSBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCJzdHJpcGVkIikKYGBgCgpgYGB7ciB0b3BfdGVybV9wZXJfY2F0ZWdvcnksIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQprbml0cjo6a2FibGUocmJpbmQodG9wX3Rlcm1zW3RvcF90ZXJtcyRzb3VyY2UgPT0gIkdPOkJQIixdWzEsXSwKICAgICAgICAgICAgICAgICAgIHRvcF90ZXJtc1t0b3BfdGVybXMkc291cmNlID09ICJHTzpNRiIsXVsxLF0sCiAgICAgICAgICAgICAgICAgICB0b3BfdGVybXNbdG9wX3Rlcm1zJHNvdXJjZSA9PSAiS0VHRyIsXVsxLF0pLAogICAgICAgICAgICAgY2FwdGlvbiA9ICJUb3AgdGVybXMgZnJvbSBlYWNoIGRhdGEgc291cmNlIHVzaW5nIGxpc3Qgb2YgYWxsIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyIpICU+JQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoInN0cmlwZWQiKQpgYGAKYGBge3IgYWxsX2Rpc3RfcGxvdH0KZ3Byb2ZpbGVyMjo6Z29zdHBsb3QodG9wX3Rlcm1zX2FsbCkgJT4lIHBsb3RseTo6bGF5b3V0KHRpdGxlID0gIk1hbmhhdHRhbiBwbG90IHNob3dpbmcgZGlzdHJpYnV0aW9uIG9mIHRlcm1zIGZyb20gZWFjaCBkYXRhIHNvdXJjZSIsIGZvbnQgPSBsaXN0KHNpemUgPSAxMCkpCmBgYAoKYGBge3IgY291bnRfdG9wX3Rlcm1zLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KbGVuZ3RoKHRvcF90ZXJtcyR0ZXJtX25hbWUpCmBgYAoKIyMgRGlzY3Vzc2lvbgoKMS4gV2UgdXNlZCBnOlByb2ZpbGVyIGFzIHdlIGhhdmUgZXh0ZW5zaXZlbHkgZGlzY3Vzc2VkIGFib3V0IGl0IGluIGNsYXNzLiBJdCBoYXMgYSBuaWNlIHdlYi1iYXNlZCBpbnRlcmZhY2UgYXMgd2VsbCBhcyBlYXN5LXRvLXVzZSBBUElzIGluIHRoZSBmb3JtIG9mIGFuIFIgcGFja2FnZS4gRnVydGhlcm1vcmUsIHRoZSBkYXRhIHNvdXJjZXMgb24gZzpQcm9maWxlciBpcyBmcmVxdWVudGx5IHVwZGF0ZWQgYW5kIGluY2x1ZGUgdGhlIGRhdGEgc291cmNlcyB0aGF0IHdlIGFyZSBtb3N0IGludGVyZXN0ZWQgaW4uCgoyLiBXZSB1c2VkIEdPIEJpb2xvZ2ljYWwgUHJvY2VzcywgR08gTW9sZWN1bGFyIEZ1bmN0aW9uLCBhbmQgS0VHTy4gV2UgY2hvc2UgdGhlc2UgZGF0YSBzb3VyY2VzIHNpbmNlIHRoZXkgYXJlIGFsc28gdXNlZCBieSB0aGUgYXV0aG9yIG9mIHRoZSBvcmlnaW5hbCBwYXBlciBmcm9tIHdoaWNoIEkgb2J0YWluZWQgdGhlIGRhdGFzZXQuIEhvd2V2ZXIsIHNpbmNlIEtFR08gaXMgYSBjb21tZXJjaWFsIGRhdGEgc291cmNlLCBpZiBpdCB3YXMgbm90IGZvciB0aGF0IGZhY3QgdGhhdCB0aGUgb3JpZ2luYWwgcGFwZXIgdXNlZCBpdCwgSSB3b3VsZCBwZXJzb25hbGx5IHJlZnJhaW4gZnJvbSB1c2luZyBpdC4gVGhlIG9yaWdpbmFsIGF1dGhvciBhbHNvIHVzZWQgb3RoZXIgZGF0YSBzb3VyY2VzIGluY2x1ZGluZyBDYW5vbmljYWwgUGF0aHdheXMgYnV0IHNpbmNlIGl0IGlzIG5vdCBwYXJ0IG9mIGc6UHJvZmlsZXIsIHdlIGRpZCBub3QgaW5jbHVkZSB0aGVzZSBkYXRhIHNvdXJjZXMuIFRoZSBhbm5vdGF0aW9uIHNvdXJjZSB2ZXJzaW9ucyBhcmUgYXMgZm9sbG93czogRW5zZW1ibCAxMDUsIEVuc2VtYmwgR2Vub21lcyA1MiAoZGF0YWJhc2UgYnVpbHQgb24gMjAyMi0wMi0xNCkKCjMuIEZvciBhbGwgdGhyZWUgYW5hbHlzaXMgKHVzaW5nIHVwcmVndWxhdGVkLCBkb3ducmVndWxhdGVkLCBhbGwgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkKSwgd2UgdXNlZCBhIHRocmVzaG9sZCBiZXR3ZWVuIDIgYW5kIDUwMC4gV2Ugc2V0IHRoZSB1cHBlciBib3VuZCB0byA1MDAgYmVjYXVzZSB3ZSBkbyBub3Qgd2FudCB0byBpbmNsdWRlIG92ZXJseSBicm9hZCBhbmQgZ2VuZXJpYyB0ZXJtcyB0aGF0IHdpbGwgbm90IGdpdmUgdXMgbWVhbmluZ2Z1bCBpbnNpZ2h0cyBpbnRvIHRoZSByb2xlcyBvZiB0aGUgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzLiBUaGUgc2V0IG9mIHVwcmVndWxhdGVkIGdlbmVzIHJldHVybmVkIDQzMyBnZW5lc2V0czsgdGhlIHNldCBvZiBkb3ducmVndWxhdGVkIGdlbmVzIHJldHVybmVkIDU2MCBnZW5lc2V0czsgdGhlIHNldCBvZiBhbGwgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIHJldHVybmVkIDYxNiBnZW5lIHNldHMuCgo0LiBUaGUgcmVzdWx0IHVzaW5nIHRoZSB3aG9sZSBsaXN0IChzZXQgb2YgYWxsIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcykgaXMgbW9yZSBwcmVkb21pbmFudGx5IHJlcHJlc2VudGVkIGJ5IHRoZSBkb3ducmVndWxhdGVkIGdlbmVzLiBJdCBhbHNvIGRvZXMgbm90IHByb3ZpZGUgYSBsb3Qgb2YgaW5zaWdodHMgaW50byB0aGUgcm9sZXMgb2YgdGhlIGdlbmVzIGFzIGl0IGlzIGEgbWl4IG9mIGRyYXN0aWNhbGx5IGRpZmZlcmVudCBhbmQgc2VlbWluZ2x5IHVucmVsYXRlZCB0ZXJtcyAoZS5nLiBtaXRvdGljIG51Y2xlYXIgZGl2aXNpb24sIG9yZ2FuZWxsZSBmaXNzaW9uLCByZXNwb25zZSB0byBlbmRvcGxhc21pYyByZXRpY3VsdW0gc3RyZXNzLCBldGMuKS4gSG93ZXZlciwgYnkgdXNpbmcgc2VwYXJhdGluZyBpbnRvIHVwcmVndWFsdGVkIGFuZCBkb3ducmVndWxhdGVkIGdlbmVzIGFuZCBwZXJmb3JtaW5nIHRoZSBnZW5lIGVucmljaG1lbnQgYW5hbHlzaXMgc2VwYXJhdGVseSwgd2UgZ2V0IG1vcmUgbWVhbmluZ2Z1bCB0ZXJtczogdGhlIHVwcmVndWFsdGVkIGdlbmVzIGFyZSBtb3N0bHkgYXNzb2NpYXRlZCB3aXRoIHBhdGh3YXlzIGFuZCBwcm9jZXNzZXMgaW52b2x2aW5nIGVuZG9wbGFzbWljIHJldGljdWx1bSB3aGVyZWFzIHRoZSBkb3ducmVndWxhdGVkIGdlbmVzIGFyZSBtb3N0bHkgYXNzb2NpYXRlZCB3aXRoIHRoZSBjZWxsIGN5Y2xlLgoKCiMgSW50ZXJwcmV0YXRpb24KCjEuIFllcy4gVGhlIG92ZXJyZXByZXNlbnRhdGlvbiBhbmFseXNpcyByZXN1bHRzIHN1cHBvcnQgdGhlIGNvbmNsdXNpb24gZGlzY3Vzc2VkIGluIHRoZSBvcmlnaW5hbCBwYXBlci4gVGhlIG9yaWdpbmFsIHBhcGVyIGNsYWltcyB0aGF0IENCRCB0cmVhdG1lbnQgY2FuIGluaGliaXQgU0FSUy1Db1YtMiByZXBsaWNhdGlvbiB0aHJvdWdoIHRoZSBob3N0J3MgRVIgc3RyZXNzIHJlc3BvbnNlIHBhdGh3YXkuIEFsdGhvdWdoIHdlIHdlcmUgbm90IGFibGUgdG8gdmVyaWZ5IHdoZXRoZXIgb3Igbm90IHRoaXMgaGFzIGFueSBhZmZlY3Qgb24gU0FSUy1Db1YtMiByZXBsaWNhdGlvbiwgd2UgYXJlIGFibGUgdG8gY29uZmlybSBiYXNlZCBvbiB0aGUgdG9wIHRlcm1zIHJldHVybmVkIGJ5IHRoZSBvdmVycmVwcmVzZW50YXRpb24gYW5hbHlzaXMgdGhhdCB0aGUgZ2VuZXMgYXNzb2NpYXRlZCB3aXRoIEVSIHN0cmVzcyByZXNwb25zZSBhcmUgaW5kZWVkIHVwcmVndWxhdGVkIGluIHRoZSBzYW1wbGVzIHRyZWF0ZWQgd2l0aCBDQkQuCgoyLiBUaGUgY29uY2x1c2lvbiB0aGF0IENCRCBpcyBjb3JyZWxhdGVkIHRvIHJlZHVjZWQgcmlzayBvciBzZXZlcml0eSBvZiBTQVJTLUNvVi0yIGlzIHN1cHBvcnRlZCBieSB0ZXN0aW5nIGFkdWx0IHBhdGllbnRzIGFzIHByZXNlbnRlZCBieSB0aGUgb3JpZ2luYWwgcGFwZXIuIFRoZXJlIGFyZSBhbHNvIG90aGVyIHBhcGVycyB3aG8gZGlzY3Vzc2VkIHRoZSByb2xlIG9mIENCRCBpbiBTQVJTLUNvVi0yIGluZmVjdGlvbiAodmFuIEJyZWVtYW4gZXQgYWwuKS4gVGhlIHJlc3VsdCBmcm9tIG91ciBvdmVycmVwcmVzZW50YXRpb24gYW5hbHlzaXMgaXMgc3VwcG9ydGVkIGJ5IHRoZSBvcmlnaW5hbCBwYXBlciwgaW4gd2hpY2ggdGhlIGF1dGhvciBoYXMgYWxzbyBwZXJmb3JtZWQgZ2VuZSBlbnJpY2htZW50IGFuYWx5c2lzIHdpdGggc2ltaWxhciBvdXRjb21lcy4gSG93ZXZlciwgc2luY2UgdGhpcyBpcyBzdGlsbCBhbiBlYXJseSByZXNlYXJjaCBpbiB0aGlzIHRvcGljIGFuZCBTQVJTLUNvVi0yIGNvbnRpbnVlcyB0byBldm9sdmUsIHRoZXJlIGRvZXMgbm90IHNlZW0gdG8gYmUgb3RoZXIgdW5yZWxhdGVkIGdyb3VwcyB3aG8gY291bGQgcHJvdmlkZSBhZGRpdGlvbmFsIHN1cHBvcnRpbmcgZXZpZGVuY2UgdG8gb3VyIHJlc3VsdHMgZnJvbSB0aGUgb3ZlcnJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIGJlc2lkZXMgdGhlIG9yaWdpbmFsIHBhcGVyLgoKIyBKb3VybmFsCgpMaW5rIHRvIG15IGpvdXJuYWwgZW50cnkgZm9yIHRoaXMgYXNzaWdubWVudDogaHR0cHM6Ly9naXRodWIuY29tL2JjYjQyMC0yMDIyL0tldmluX0dhby93aWtpL0Fzc2lnbm1lbnQtMgoKIyBSZWZlcmVuY2VzCgotIENoZW4gWSwgTHVuIEFUTCwgU215dGggR0sgKDIwMTYpLiBGcm9tIHJlYWRzIHRvIGdlbmVzIHRvIHBhdGh3YXlzOiBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyBvZiBSTkEtU2VxIGV4cGVyaW1lbnRzIHVzaW5nIFJzdWJyZWFkIGFuZCB0aGUKICBlZGdlUiBxdWFzaS1saWtlbGlob29kIHBpcGVsaW5lLiBGMTAwMFJlc2VhcmNoIDUsIDE0MzgKLSBEdXJpbmNrLCBTLiwgU3BlbGxtYW4sIFAuIFQuLCBCaXJuZXksIEUuLCAmIEh1YmVyLCBXLiAoMjAwOSkuIE1hcHBpbmcgaWRlbnRpZmllcnMgZm9yIHRoZSBpbnRlZ3JhdGlvbiBvZiBnZW5vbWljIGRhdGFzZXRzIHdpdGggdGhlIFIvQmlvY29uZHVjdG9yIHBhY2thZ2UgYmlvbWFSdC4gTmF0dXJlIC0gcHJvdG9jb2xzLCA0KDgpLCAxMTg04oCTMTE5MS4gaHR0cHM6Ly9kb2kub3JnLzEwLjEwMzgvbnByb3QuMjAwOS45NwotIE1hcnRpbiBNb3JnYW4gKDIwMjEpLiBCaW9jTWFuYWdlcjogQWNjZXNzIHRoZSBCaW9jb25kdWN0b3IgUHJvamVjdCBQYWNrYWdlIFJlcG9zaXRvcnkuIFIgcGFja2FnZSB2ZXJzaW9uIDEuMzAuMTYuCiAgaHR0cHM6Ly9DUkFOLlItcHJvamVjdC5vcmcvcGFja2FnZT1CaW9jTWFuYWdlcgotIE1jQ2FydGh5IERKLCBDaGVuIFkgYW5kIFNteXRoIEdLICgyMDEyKS4gRGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgb2YgbXVsdGlmYWN0b3IgUk5BLVNlcSBleHBlcmltZW50cyB3aXRoIHJlc3BlY3QgdG8gYmlvbG9naWNhbAogIHZhcmlhdGlvbi4gTnVjbGVpYyBBY2lkcyBSZXNlYXJjaCA0MCwgNDI4OC00Mjk3Ci0gTmd1eWVuLCBMLiBDLiwgWWFuZywgRC4sIE5pY29sYWVzY3UsIFYuLCBCZXN0LCBULiBKLiwgT2h0c3VraSwgVC4sIENoZW4sIFMuLU4uLCBGcmllc2VuLCBKLiBCLiwgRHJheW1hbiwgTi4sIE1vaGFtZWQsIEEuLCBEYW5uLCBDLiwgU2lsdmEsIEQuLCBHdWxhLCBILiwgSm9uZXMsIEsuIEEuLCBNaWxsaXMsIEouIE0uLCBEaWNraW5zb24sIEIuIEMuLCBUYXksIFMuLCBPYWtlcywgUy4gQS4sIFBhdWxpLCBHLiBGLiwgTWVsdHplciwgRC4gTy4sIOKApiBSb3NuZXIsIE0uIFIuICgyMDIxKS4gQ2FubmFiaWRpb2wgaW5oaWJpdHMgU0FSUy1DT1YtMiByZXBsaWNhdGlvbiBhbmQgcHJvbW90ZXMgdGhlIGhvc3QgaW5uYXRlIGltbXVuZSByZXNwb25zZS4gU2NpZW5jZSBBZHZhbmNlcy4gaHR0cHM6Ly93d3cuc2NpZW5jZS5vcmcvZG9pL2Ficy8xMC4xMTI2L3NjaWFkdi5hYmk2MTEwCi0gUm9iaW5zb24gTUQsIE1jQ2FydGh5IERKIGFuZCBTbXl0aCBHSyAoMjAxMCkuIGVkZ2VSOiBhIEJpb2NvbmR1Y3RvciBwYWNrYWdlIGZvciBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyBvZiBkaWdpdGFsIGdlbmUgZXhwcmVzc2lvbiBkYXRhLgogIEJpb2luZm9ybWF0aWNzIDI2LCAxMzktMTQwCi0gR3UsIFouICgyMDE2KSBDb21wbGV4IGhlYXRtYXBzIHJldmVhbCBwYXR0ZXJucyBhbmQgY29ycmVsYXRpb25zIGluIG11bHRpZGltZW5zaW9uYWwgZ2Vub21pYyBkYXRhLiBCaW9pbmZvcm1hdGljcy4KLSBLb2xiZXJnIEwsIFJhdWR2ZXJlIFUsIEt1em1pbiBJLCBWaWxvIEosIFBldGVyc29uIEggKDIwMjApLiDigJxncHJvZmlsZXIyLSBhbiBSIHBhY2thZ2UgZm9yIGdlbmUgbGlzdCBmdW5jdGlvbmFsIGVucmljaG1lbnQKYW5hbHlzaXMgYW5kIG5hbWVzcGFjZSBjb252ZXJzaW9uIHRvb2xzZXQgZzpQcm9maWxlci7igJ0gX0YxMDAwUmVzZWFyY2hfLCAqOSAoRUxJWElSKSooNzA5KS4gUiBwYWNrYWdlIHZlcnNpb24gMC4yLjEuCi0gU3RlZmFuIE1pbHRvbiBCYWNoZSBhbmQgSGFkbGV5IFdpY2toYW0gKDIwMjApLiBtYWdyaXR0cjogQSBGb3J3YXJkLVBpcGUgT3BlcmF0b3IgZm9yIFIuIGh0dHBzOi8vbWFncml0dHIudGlkeXZlcnNlLm9yZywKICBodHRwczovL2dpdGh1Yi5jb20vdGlkeXZlcnNlL21hZ3JpdHRyLgotIHZhbiBCcmVlbWVuLCBSLiBCLiwgTXVjaGlyaSwgUi4gTi4sIEJhdGVzLCBULiBBLiwgV2VpbnN0ZWluLCBKLiBCLiwgTGVpZXIsIEguIEMuLCBGYXJsZXksIFMuLCAmIFRhZmVzc2UsIEYuIEcuICgyMDIyKS4gQ2FubmFiaW5vaWRzIEJsb2NrIENlbGx1bGFyIEVudHJ5IG9mIFNBUlMtQ29WLTIgYW5kIHRoZSBFbWVyZ2luZyBWYXJpYW50cy4gSm91cm5hbCBvZiBuYXR1cmFsIHByb2R1Y3RzLCA4NSgxKSwgMTc24oCTMTg0LiBodHRwczovL2RvaS5vcmcvMTAuMTAyMS9hY3Muam5hdHByb2QuMWMwMDk0Ng==